package com.test.event;

import com.test.factory.BeanFactory;
import com.test.listener.ApplicationListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 简单的应用事件多播器实现类
 * 负责将事件广播给所有感兴趣的监听器
 */
public class SimpleApplicationEventMulticaster implements ApplicationEventMulticaster{

    //保存所有监听器
    private final List<ApplicationListener<?>> listeners = new ArrayList<>();

    //用于创建监听器实例
    private BeanFactory beanFactory;

    //无参构造函数
    public SimpleApplicationEventMulticaster() {
    }

    //有参构造函数，初始化BeanFactory
    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    //设置BeanFactory
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    //添加应用监听器
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        listeners.add(listener);
    }

    //移除应用监听器
    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        listeners.remove(listener);
    }

    //移除所有监听器
    @Override
    public void removeAllListeners() {
        listeners.clear();
    }

    //广播事件给所有感兴趣的监听器
    @Override
    public void multicastEvent(ApplicationEvent event) {
        for (ApplicationListener listener : getApplicationEvent(event)){
            invokeListener(listener, event);
        }
    }

    //获取当前事件对应的所有监听器
    private Collection<ApplicationListener> getApplicationEvent(ApplicationEvent event) {
        List<ApplicationListener> allListeners = new ArrayList<>();
        for (ApplicationListener<?> listener : listeners) {
            if (supportsEvent(listener, event)) {
                allListeners.add(listener);
            }
        }
        return allListeners;
    }

    //检查监听器是否支持当前事件
    private boolean supportsEvent(ApplicationListener<?> listener, ApplicationEvent event) {
        //简化实现，默认所有监听器都支持所有时间
        //实际Spring中会使用反射检查泛型类型
        return true;
    }

    //调用监听器的事件处理方法
    private void invokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (Exception ex){
            System.out.println("处理时间时发生错误：" + ex.getMessage());
        }
    }
}
